/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_core.h                                                    */
/*  NOTE      =                                                               */
/*  DATE      = 2014/09/28 by zhengxd                                         */
/******************************************************************************/
#ifndef _db2_CORE_H_
#define _db2_CORE_H_

#include "db2_base_type.h"

/*
 *  分片包数据
*/
typedef struct __st_L7_fragment_db2 {

    int i_exter_flg;                      /* Externalized flag */
    int i_exter_whole_flg;                /* Externalized whole flag */
    unsigned int ui_hdr_len;              /* DDM头部长度 */
    int i_req_resp_flg;                   /* request/response flag */
    int i_last_ddm_flg;                   /* 是否是最后一个DDM */
    int i_next_correlator;                /* 下一个correlator */
    int i_residual_ddm_head_len;          /* 残留DDM的头数据长度 */
    uint64_t u64_remain_len;              /* 最后一个DDM还需要接受的数据长度 */
    uint64_t u64_parsed_index;            /* 解析到的位置 */
    int i_correlator_flg;                 /* correlator标识 */
    int i_req_resp_cp;                    /* 当前解析到的request或者response的code point */
    unsigned int ui_left_ddm_len;         /* 当前DDM剩余为解析长度 */
    int i_obj_cp;                         /* 当前解析到的object的code point */
    unsigned int ui_left_obj_len;         /* 当前OBJECT剩余为解析长度 */
    int i_param_cp;                       /* 当前解析到的参数的code point */
    unsigned int ui_param_len;            /* 当前参数长度 */
    Frbyte_Packet *p_st_data;             /* packet数据 */
    struct timeval st_start_timestamp;    /* 开始分片包的时间 */
    struct timeval st_timestamp;          /* 分片包的时间 */
} L7_fragment_db2;

/*
 *   L7session_db2 用于存放db2私有的session数据, 对应L7_session的p_session_private变量
 *    通用的username、session_starttime、session_stoptime
*/
typedef struct __st_L7session_db2 {

    int i_confirmed_flg;                  /* 链接信息是不是确定的 */
    int i_cli_typdef;                     /* 客户端的TYPEDEFN */
    int i_ser_typdef;                     /* 服务端的TYPEDEFN */
    char *p_cli_host_user;                /* 客户端的主机名 */
    char *p_program;                      /* 客户端的程序名 */
    char *p_db_name;                      /* 数据库名 */
    char *p_db_user;                      /* 登陆用户名 */
    char arr_ccsid[16];                   /* 参数用CCSID */
    struct timeval st_login;
} L7session_db2;

/*
 *  DB2请求
 *  对应L7_requestdata中的p_request_private数据
*/
typedef struct __st_L7_req_db2 {

    int i_need_req_resp;                  /* 下一个所需数据类型 */
    int i_typdef;                         /* TYPDEF */
    unsigned int ui_ddm_len;              /* 当前DDM的长度(command+object) */
    char *p_sql;                          /* 当前DDM的SQL */
    long l_cursor_id;                     /* 当前DDM的session ID */
    Sql_statement *p_st_statement;        /* 当前DDM的对应游标数据 */
    Sql_resultset *p_st_resultset;        /* 当前DDM的对应结果集索引 */
    Frlist_header st_metadata;            /* 当前DDM的metadata */
    Frlist_header st_bind;                /* bind参数列表 */

    Db2_req_cmd *p_st_command_pre;        /* 上一个DDM信息 */
    Frlist_header st_command_lst;         /* Command列表 */
} L7_req_db2;

/*
 *  DB2响应
 *  解析response过程中的数据
*/
typedef struct __st_L7_resp_db2 {

    int i_error_code;                      /* 错误号 */
    unsigned int ui_ddm_len;              /* 一个DDM command响应的长度 */
    unsigned long ul_effect_rows;         /* 影响行数 */
    unsigned long ul_rows;                /* fetch行数 */
    int64_t i64_svrcod;                    /* 错误号 */
    char *p_error_msg;                    /* 错误信息 */
    int i_parsed_index;                   /* 解析到对应request Command的位置 */
    char arr_sqlstate[6];                 /* 错误状态(5位) */
}L7_resp_db2;

/*
 *  DB2私有数据
*/
typedef struct __st_L7session_db2_private {

    L7_fragment_db2 *p_st_fragment;       /* 分片包数据 */
    L7session_db2 *p_st_sess;             /* session数据 */
    L7_req_db2 *p_st_req;                 /* request数据 */
    L7_resp_db2 *p_st_resp;               /* 临时response信息 */
    Frhash_header *p_hash_prepare;        /* prepare数据(Sql_statement *) */
} L7session_db2_private;

int db2_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet);

int db2_analysis(Conntrack *p_st_conn
                , Apm_packet *p_st_packet
                , Frhash_header *p_st_hash_report);

int db2_session_destroy(void *p_private_session);

#endif
